home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-09-17 | 4.4 KB | 163 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWClaImp.cpp
- // Release Version: $ ODF 2 $
- //
- // Copyright: (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "FWFound.hpp"
-
- #ifndef FWCLAIMP_H
- #include "FWClaImp.h"
- #endif
-
- #ifdef FW_BUILD_MAC
- #pragma segment FW_ClassInfo
- #endif
-
- //----------------------------------------------------------------------------------------
- // IsKindOf
- //----------------------------------------------------------------------------------------
-
- static FW_Boolean IsKindOf(FW_SClassInfoPtr derived, FW_SClassInfoPtr base)
- {
- FW_Boolean result = false;
-
- if (base == derived)
- result = true;
- else
- {
- FW_SClassInfoPtr const *ancestors = derived->fAncestors;
-
- while (*ancestors != 0)
- {
- if (IsKindOf(*ancestors,base))
- {
- result = true;
- break;
- }
- ancestors++;
- }
- }
- return result;
- }
-
- //----------------------------------------------------------------------------------------
- // IsKindOf
- //----------------------------------------------------------------------------------------
-
- static FW_Boolean OffsetToBase(FW_SClassInfoPtr derived, FW_SClassInfoPtr base, size_t& offset)
- {
- FW_Boolean result = false;
-
- if (base == derived)
- {
- offset = 0;
- result = true;
- }
- else
- {
- FW_SClassInfoPtr const *ancestors = derived->fAncestors;
-
- while (*ancestors != 0)
- {
- if (OffsetToBase(*ancestors, base, offset))
- {
- offset += derived->fAncestorOffsets[ancestors - derived->fAncestors];
- result = true;
- break;
- }
- ancestors++;
- }
- }
-
- return result;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivDynamicCast
- //----------------------------------------------------------------------------------------
-
- void* FW_PrivDynamicCast(const void* p,
- FW_SClassInfoPtr fromDynamicClass,
- FW_SClassInfoPtr fromStaticClass,
- FW_SClassInfoPtr toStaticClass)
- {
- size_t offset;
- char *q = 0;
-
- if (p!=0)
- {
- if ((fromStaticClass == toStaticClass) && IsKindOf(fromDynamicClass, toStaticClass))
- {
- q = (char*) p;
- }
- else if (OffsetToBase(fromDynamicClass, toStaticClass, offset))
- {
- q = (char*) p;
- q += offset;
- FW_Boolean isKindOf = OffsetToBase(fromDynamicClass, fromStaticClass, offset);
- if (!isKindOf)
- {
- FW_PRIV_ASSERT(isKindOf);
- // If we get here, the declared pointer type was
- // not consistent with the runtime type of the object!
- // That could only happen if somewhere else a bad cast
- // (perhaps from a void*) was done.
- return 0;
- }
- q -= offset;
- }
- }
-
- return q;
- }
-
- // Consider this code fragment:
- //
- // template <class TActual, class TKnown, class TTarget>
- // foo()
- // {
- // TKnown *p = new TActual();
- // TTarget *t = dynamic_cast<TTarget*>(p);
- // }
- //
- // TActual is the actual runtime type of the object.
- // TKnown is the compile-time type of the pointer variable that points
- // to the object.
- // TTarget is the compile-time type that we are attempting to cast
- // the pointer to.
- //
- // Now, assume an operator IsKindOf(TDerived, TBase) that returns true
- // if class TDerived is derived from class TBase.
- //
- // Given this, the result of the dynamic_cast above will be nonzero
- // if and only if IsKindOf(TActual, TTarget). However, there are
- // interesting subvariations. In the following, assume
- // IsKindOf(TActual, TTarget):
- //
- // The cast is a simple upcast if IsKindOf(TKnown, TTarget). Upcasting
- // never needs a dynamic_cast, i.e. it can be done with a simple cast
- // (TTarget*). Since ODF uses emulation, it is better to avoid
- // dynamic casts in this instance.
- //
- // The cast is a standard downcast if IsKindOf(TTarget, TKnown). This
- // is the most common case for dynamic_casts.
- //
- // The cast is a sidecast if it is neither an upcast or a downcast, i.e.
- // a valid sidecast requires three conditions:
- //
- // IsKindOf(TActual, TTarget) &&
- // !IsKindOf(TKnown, TTarget) &&
- // !IsKindOf(TTarget, TKnown)
- //
- // Sidecasts happen with mixin style programming. Assume classes
- // CBase, MMixin, and CDerived, where CDerived inherits from both
- // CBase and MMixin. A CBase* that points to a CDerived can be
- // successfully cast to a MMixin*, even if the code that contains
- // the dynamic_cast has no knowledge of the class CDerived, so
- // there is apparently no relationship between the known type and
- // the target type.
-